// Copyright (c) 2023 Institute of Software, Chinese Academy of Sciences
// Ripple is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.

package ripple.server.tcp.handler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ripple.common.DebugTool;
import ripple.common.entity.*;
import ripple.common.tcp.Handler;
import ripple.common.tcp.Message;
import ripple.common.tcp.message.ReformSyncRequest;
import ripple.common.tcp.message.ReformSyncResponse;
import ripple.server.core.Node;

import java.net.InetSocketAddress;


public class ReformSyncRequestHandler implements Handler {
    private static final Logger LOGGER = LoggerFactory.getLogger(ReformSyncRequestHandler.class);

    private Node node;

    private Node getNode() {
        return node;
    }

    private void setNode(Node node) {
        this.node = node;
    }

    public ReformSyncRequestHandler(Node node) {
        this.setNode(node);
    }

    @Override
    public Message handle(ChannelHandlerContext channelHandlerContext, Message message) {
        ReformSyncRequest reformSyncRequest = (ReformSyncRequest) message;
        InetSocketAddress localAddress = ((NioSocketChannel) channelHandlerContext.channel()).localAddress();
        InetSocketAddress remoteAddress = ((NioSocketChannel) channelHandlerContext.channel()).remoteAddress();

        boolean result = false;

        AbstractMessage msg = null;
        if (reformSyncRequest.getOperationType().equals(Constants.REFORM_PREPARE)) {
//            LOGGER.info("[ReformSyncRequestHandler] [{}:{}<-->{}:{}] Receive SYNC request. UUID = {}, Message UUID = {}" +
//                            ", Operation Type = {}, Last Update = {}" +
//                            ", Last Update Server Id = {}."
//                    , localAddress.getHostString(), localAddress.getPort(), remoteAddress.getHostString()
//                    , remoteAddress.getPort(), reformSyncRequest.getUuid(), reformSyncRequest.getMessageUuid()
//                    , reformSyncRequest.getOperationType()
//                    , SimpleDateFormat.getDateTimeInstance().format(reformSyncRequest.getLastUpdate())
//                    , reformSyncRequest.getLastUpdateServerId());
            msg = ReformRequest.prepare(reformSyncRequest.getMessageUuid()
                    , reformSyncRequest.getLastUpdate(), reformSyncRequest.getLastUpdateServerId());
//        } else if (reformSyncRequest.getOperationType().equals(Constants.REFORM_PROPOSE)) {
//            LOGGER.info("[ReformSyncRequestHandler] [{}:{}<-->{}:{}] Receive SYNC request. UUID = {}, Message UUID = {}" +
//                            ", Operation Type = {}, ReformList String = {}, Last Update = {}" +
//                            ", Last Update Server Id = {}."
//                    , localAddress.getHostString(), localAddress.getPort(), remoteAddress.getHostString()
//                    , remoteAddress.getPort(), reformSyncRequest.getUuid(), reformSyncRequest.getMessageUuid()
//                    , reformSyncRequest.getOperationType(), Reform.ListToString(reformSyncRequest.getReformList())
//                    , SimpleDateFormat.getDateTimeInstance().format(reformSyncRequest.getLastUpdate()), reformSyncRequest.getLastUpdateServerId());
//            msg = new DeleteMessage(reformSyncRequest.getMessageUuid(), Reform.ListToString(reformSyncRequest.getReformList())
//                    , reformSyncRequest.getLastUpdate(), reformSyncRequest.getLastUpdateServerId());
//        } else if (reformSyncRequest.getOperationType().equals(Constants.REFORM_COMMIT)) {
////            LOGGER.info("[ReformSyncRequestHandler] [{}:{}<-->{}:{}] Receive SYNC request. UUID = {}, Message UUID = {}" +
////                            ", Operation Type = {}, Application Name = {}, Key = {}, Base Message UUID = {}" +
////                            ", Atomic Operation = {}, Value = {}, Last Update = {}, Last Update Server Id = {}."
////                    , localAddress.getHostString(), localAddress.getPort(), remoteAddress.getHostString()
////                    , remoteAddress.getPort(), reformSyncRequest.getUuid(), reformSyncRequest.getMessageUuid()
////                    , reformSyncRequest.getOperationType(), reformSyncRequest.getApplicationName(), reformSyncRequest.getKey()
////                    , reformSyncRequest.getBaseMessageUuid(), reformSyncRequest.getAtomicOperation(), reformSyncRequest.getValue()
////                    , SimpleDateFormat.getDateTimeInstance().format(reformSyncRequest.getLastUpdate()), reformSyncRequest.getLastUpdateServerId());
//            msg = new IncrementalUpdateMessage(reformSyncRequest.getMessageUuid(),
//                    , reformSyncRequest.getBaseMessageUuid(), reformSyncRequest.getAtomicOperation()
//                    , reformSyncRequest.getLastUpdate(), reformSyncRequest.getLastUpdateServerId());
        }

        DebugTool.write("server " + this.getNode().getId() + " receive reform sync.");

        result = this.getNode().propagateReformMessage(msg);

        ReformSyncResponse reformSyncResponse = new ReformSyncResponse();
        reformSyncResponse.setUuid(reformSyncRequest.getUuid());
        reformSyncResponse.setSuccess(result);
        LOGGER.info("[reformSyncRequestHandler] [{}:{}<-->{}:{}] Send SYNC response. UUID = {}, Success = {}."
                , localAddress.getHostString(), localAddress.getPort(), remoteAddress.getHostString()
                , remoteAddress.getPort(), reformSyncResponse.getUuid(), reformSyncResponse.isSuccess());
        return reformSyncResponse;
    }
}